package jmine.tec.hydra.web.pages.especificacao;

import static jmine.tec.hydra.web.HydraWebMessages.ERRO_HYDRA_SPECIFICATION_JA_ATIVADA;
import static jmine.tec.hydra.web.HydraWebMessages.ERRO_HYDRA_SPECIFICATION_JA_DESATIVADA;
import static jmine.tec.hydra.web.HydraWebMessages.INFO_HYDRA_SPECIFICATION_ATIVADA_SUCESSO;
import static jmine.tec.hydra.web.HydraWebMessages.INFO_HYDRA_SPECIFICATION_DESATIVADA_SUCESSO;
import images.ImageResources;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import jmine.tec.hydra.HydraController;
import jmine.tec.hydra.dao.HydraSpecificationDAO;
import jmine.tec.hydra.domain.HydraSystem;
import jmine.tec.hydra.domain.specification.HydraSpecificationImpl;
import jmine.tec.web.exception.WebWicketException;
import jmine.tec.web.pages.HelpTextMessages;
import jmine.tec.web.wicket.component.autocomplete.NaturalKeyAutocomplete;
import jmine.tec.web.wicket.component.button.ActionSubmitLink;
import jmine.tec.web.wicket.pages.Template;

import org.apache.wicket.ResourceReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.SubmitLink;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.image.Image;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.spring.injection.annot.SpringBean;

import bancosys.tec.exception.LocalizedMessageHolder;
import bancosys.tec.exception.MessageCreator;
import bancosys.tec.persist.dao.BaseDAO;
import bancosys.tec.security.annotation.Secure;
import bancosys.tec.security.authorization.UrlPermission;

/**
 * Tela de consulta das integrações hydra.
 * 
 * @author Renan Kuroki
 * @created 03/01/2011
 */
@Secure(id = "URL_LIST_INTEGRACAO_ESPECIFICACAO", permissionType = UrlPermission.class)
public class ConsultaIntegracaoEspecificacao extends Template {

    protected static final int INITIAL_WIDTH_MODAL = 1000;

    protected static final int INITIAL_HEIGHT_MODAL = 350;

    private Form<HydraSpecificationImpl> form = null;

    @SpringBean(name = "hydraController")
    private HydraController hydraController;

    private List<HydraSpecificationRowData> hydraSpecificationList = new ArrayList<HydraSpecificationRowData>();

    /**
     * Construtor.
     */
    public ConsultaIntegracaoEspecificacao() {
        super();
        HydraSpecificationDAO dao = this.hydraController.getDAOFactory().getDAOByClass(HydraSpecificationDAO.class);
        List<HydraSpecificationImpl> listaHydraSpecificationImpl = dao.findAll();
        this.hydraSpecificationList = this.convertHydraSpecificationList(listaHydraSpecificationImpl);
        this.initForm();
    }

    /**
     * Inicializa o form.
     */
    private void initForm() {
        this.form = new Form<HydraSpecificationImpl>("mainForm") {
            @Override
            protected void onSubmit() {
                ConsultaIntegracaoEspecificacao.this.submitForm();
            }
        };
        this.add(new FeedbackPanel("feedback"));

        BaseDAO<HydraSpecificationImpl> dao = this.hydraController.getDAOFactory().getGenericDAO(HydraSpecificationImpl.class);
        HydraSpecificationImpl hydraSpecification = dao.createBean();
        this.form.setModel(new Model<HydraSpecificationImpl>(hydraSpecification));

        NaturalKeyAutocomplete<HydraSystem> hydraSystemAutoComplete = new NaturalKeyAutocomplete<HydraSystem>(HydraSystem.class, "sistema");
        hydraSystemAutoComplete.setModel(new PropertyModel<HydraSystem>(hydraSpecification, "system"));
        this.form.add(hydraSystemAutoComplete);

        this.form.add(new TextField<String>("acao", new PropertyModel<String>(hydraSpecification, "action")));

        ListView<HydraSpecificationRowData> hydraSpecificationListView =
                new ListView<HydraSpecificationRowData>("hydraSpecificationList", new PropertyModel<List<HydraSpecificationRowData>>(this,
                        "hydraSpecificationList")) {

                    @Override
                    protected void populateItem(ListItem<HydraSpecificationRowData> item) {
                        final HydraSpecificationRowData hydraSpecRowData = item.getModelObject();
                        CheckBox lstSelecaoSpecification =
                                new CheckBox("lstSelecaoSpecification", new PropertyModel<Boolean>(hydraSpecRowData, "isSelecionado"));
                        lstSelecaoSpecification.setOutputMarkupId(true);
                        lstSelecaoSpecification.add(new AjaxFormComponentUpdatingBehavior("onchange") {
                            @Override
                            protected void onUpdate(AjaxRequestTarget target) {
                                // método implementado conseguir buscar os checkbox selecionados
                            }
                        });
                        item.add(lstSelecaoSpecification);
                        item.add(new Label("lstSistema", new PropertyModel<String>(hydraSpecRowData, "specification.system")));
                        item.add(new Label("lstAcao", new PropertyModel<String>(hydraSpecRowData, "specification.action")));
                        item.add(new Label("lstStatus", new PropertyModel<String>(hydraSpecRowData, "status")));
                        item.add(new Label("lstEmissor", new PropertyModel<String>(hydraSpecRowData, "emissor")));
                        item.add(new Label("lstCodificacao", new PropertyModel<String>(hydraSpecRowData,
                                "specification.encodeScript.mnemonico")));
                        item.add(new Label("lstDecodificacao", new PropertyModel<String>(hydraSpecRowData,
                                "specification.decodeScript.mnemonico")));
                        item.add(new Label("lstModelo", new PropertyModel<String>(hydraSpecRowData, "specification.template.mnemonico")));

                        final ModalWindow modalEspecificacao = new ModalWindow("modalPanelDetalhe");
                        modalEspecificacao.setInitialWidth(INITIAL_WIDTH_MODAL);
                        modalEspecificacao.setInitialHeight(INITIAL_HEIGHT_MODAL);
                        modalEspecificacao.setContent(new ModalPanelDetalheEspecificacao(modalEspecificacao.getContentId(),
                                hydraSpecRowData));
                        modalEspecificacao.setTitle("Detalhe Especificação");
                        item.add(modalEspecificacao);

                        AjaxLink<HydraSpecificationRowData> btnDetalhe =
                                new AjaxLink<HydraSpecificationRowData>("lstBtnDetalheSpecification") {
                                    @Override
                                    public void onClick(AjaxRequestTarget target) {
                                        modalEspecificacao.show(target);
                                    }
                                };
                        btnDetalhe.add(new Image("lupa", new ResourceReference(ImageResources.class, "magnifier.png")));

                        item.add(btnDetalhe);
                    }
                };
        hydraSpecificationListView.setOutputMarkupId(true);
        this.add(hydraSpecificationListView);

        SubmitLink btnAtivar = new ActionSubmitLink("btnAtivar") {
            @Override
            public void onAction() {
                ConsultaIntegracaoEspecificacao.this.ativarSpecification();
                this.setResponsePage(new ConsultaIntegracaoEspecificacao());
            }
        };
        this.form.add(btnAtivar);

        SubmitLink btnDesativar = new ActionSubmitLink("btnDesativar") {
            @Override
            public void onAction() {
                ConsultaIntegracaoEspecificacao.this.desativarSpecification();
                this.setResponsePage(new ConsultaIntegracaoEspecificacao());
            }
        };
        this.form.add(btnDesativar);

        this.add(this.form);
    }

    /**
     * Rodado no submit do form.
     */
    private void submitForm() {
        HydraSpecificationDAO dao = this.hydraController.getDAOFactory().getDAOByClass(HydraSpecificationDAO.class);
        HydraSpecificationImpl hydraSpecification = this.form.getModelObject();
        List<HydraSpecificationImpl> listaHydraSpecificationImpl =
                dao.findBySystemActionLike(hydraSpecification.getSystem(), hydraSpecification.getAction());
        this.hydraSpecificationList = this.convertHydraSpecificationList(listaHydraSpecificationImpl);
    }

    /**
     * Método que ativa as Specifications selecionadas na tela.
     */
    protected void ativarSpecification() {
        for (HydraSpecificationRowData hydraSpecRow : this.hydraSpecificationList) {
            if (hydraSpecRow.getIsSelecionado()) {
                try {
                    hydraSpecRow.ativar();
                    LocalizedMessageHolder msg =
                            INFO_HYDRA_SPECIFICATION_ATIVADA_SUCESSO.create(hydraSpecRow.getSpecification().getSystem(), hydraSpecRow
                                    .getSpecification().getAction());
                    ConsultaIntegracaoEspecificacao.this.info(msg.getMessage());
                } catch (WebWicketException e) {
                    ConsultaIntegracaoEspecificacao.this.error(e.getLocalizedMessage());
                }
            }
        }
    }

    /**
     * Método que desativa as Specifications selecionadas na tela.
     */
    protected void desativarSpecification() {
        for (HydraSpecificationRowData hydraSpecRow : this.hydraSpecificationList) {
            if (hydraSpecRow.getIsSelecionado()) {
                try {
                    hydraSpecRow.desativar();
                    LocalizedMessageHolder msg =
                            INFO_HYDRA_SPECIFICATION_DESATIVADA_SUCESSO.create(hydraSpecRow.getSpecification().getSystem(), hydraSpecRow
                                    .getSpecification().getAction());
                    ConsultaIntegracaoEspecificacao.this.info(msg.getMessage());
                } catch (WebWicketException e) {
                    ConsultaIntegracaoEspecificacao.this.error(e.getLocalizedMessage());
                }
            }
        }
    }

    /**
     * @return the hydraSpecificationList
     */
    public List<HydraSpecificationRowData> getHydraSpecificationtList() {
        return this.hydraSpecificationList;
    }

    /**
     * @param hydraSpecificationList the hydraSpecificationList to set
     */
    public void setHydraSpecificationList(List<HydraSpecificationRowData> hydraSpecificationList) {
        this.hydraSpecificationList = hydraSpecificationList;
    }

    /**
     * Cria uma lista de {@link HydraSpecificationRowData} a partir de uma lista de {@link HydraSpecificationImpl}.
     * 
     * @param listHydraSpecificationImpl the hydraSpecificationList to set
     * @return uma lista de {@link HydraSpecificationRowData}
     */
    private List<HydraSpecificationRowData> convertHydraSpecificationList(List<HydraSpecificationImpl> listHydraSpecificationImpl) {
        List<HydraSpecificationRowData> listHydraSpecificationRowData = new ArrayList<HydraSpecificationRowData>();
        for (HydraSpecificationImpl hydraSpecImpl : listHydraSpecificationImpl) {
            listHydraSpecificationRowData.add(new HydraSpecificationRowData(hydraSpecImpl, Boolean.FALSE));
        }
        return listHydraSpecificationRowData;
    }

    /**
     * Inner Class auxiliar para criação da lista de {@link HydraSpecificationImpl}, com opção de ativação/desativação.
     * 
     * @author Renan Kuroki
     * @created 04/01/2011
     */
    protected class HydraSpecificationRowData implements Serializable {

        /**
         * Construtor.
         * 
         * @param specification HydraSpecificationImpl
         * @param isSelecionado Boolean
         */
        public HydraSpecificationRowData(HydraSpecificationImpl specification, Boolean isSelecionado) {
            this.specification = specification;
            this.isSelecionado = isSelecionado;
        }

        private HydraSpecificationImpl specification;

        private Boolean isSelecionado;

        /**
         * @return o status (Ativado/Desativado).
         */
        public String getStatus() {
            if (this.specification.isEnabled()) {
                return "Ativado";
            } else {
                return "Desativado";
            }
        }

        /**
         * @return o mnemonico do Emissor
         */
        public String getEmissor() {
            if (this.specification.getSenderRegistry() != null) {
                return this.specification.getSenderRegistry().getMnemonico();
            }
            return null;
        }

        /**
         * @return a descrição do emissor.
         */
        public String getDescricaoEmissor() {
            return this.specification.getSenderRegistry() == null ? "" : this.specification.getSenderRegistry().toString();
        }

        /**
         * @return the isSelecionado
         */
        public Boolean getIsSelecionado() {
            return this.isSelecionado;
        }

        /**
         * @param isSelecionado the isSelecionado to set
         */
        public void setIsSelecionado(Boolean isSelecionado) {
            this.isSelecionado = isSelecionado;
        }

        /**
         * @return the specification
         */
        public HydraSpecificationImpl getSpecification() {
            return this.specification;
        }

        /**
         * @param specification the specification to set
         */
        public void setSpecification(HydraSpecificationImpl specification) {
            this.specification = specification;
        }

        /**
         * Ativa o {@link HydraSpecificationImpl}.
         * 
         * @throws WebWicketException sobe mensagem de exceção.
         */
        public void ativar() throws WebWicketException {
            if (!this.specification.isEnabled()) {
                this.specification.enable();
                this.specification.getPersister().save();
            } else {
                throw new WebWicketException(ERRO_HYDRA_SPECIFICATION_JA_ATIVADA.create(this.specification.getSystem(),
                        this.specification.getAction()));
            }
        }

        /**
         * Desativa o {@link HydraSpecificationImpl}.
         * 
         * @throws WebWicketException sobe mensagem de exceção.
         */
        public void desativar() throws WebWicketException {
            if (this.specification.isEnabled()) {
                this.specification.disable();
                this.specification.getPersister().save();
            } else {
                throw new WebWicketException(ERRO_HYDRA_SPECIFICATION_JA_DESATIVADA.create(this.specification.getSystem(),
                        this.specification.getAction()));
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected MessageCreator getHelpTextCreator() {
        return HelpTextMessages.CONSULTA_INTEGRACAO_ESPECIFICACAO;
    }
}